using System;
using System.Collections;
using System.ComponentModel;
using System.Reflection;
using System.Windows.Forms;

namespace sharpCash.ReflectionClasses
{
    public static class ObjectStringClass
    {
        static public object findObjectByName(string objName)
        {
            string nameSearch = objName;
            if (!objName.Contains("sharpCash"))
                nameSearch = "sharpCash." + objName;
            Type[] myTypes = Assembly.GetEntryAssembly().GetTypes();
            object rv = null;
            foreach (Type tmpType in myTypes)
            {
                if (tmpType.FullName == nameSearch)
                {
                    rv = tmpType.GetConstructor(new Type[] { }).Invoke(new object[] { });
                    break;
                }
            }
            if (rv == null)
            {
                myTypes = Assembly.Load("BaseClasses").GetTypes();
                foreach (Type tmpType in myTypes)
                {
                    if (tmpType.FullName == nameSearch)
                    {
                        rv = tmpType.GetConstructor(new Type[] { }).Invoke(new object[] { });
                        break;
                    }
                }
            }
            if (rv == null)
            {
                myTypes = Assembly.GetExecutingAssembly().GetTypes();
                foreach (Type tmpType in myTypes)
                {
                    if (tmpType.FullName == nameSearch)
                    {
                        rv = tmpType.GetConstructor(new Type[] { }).Invoke(new object[] { });
                        break;
                    }
                }
            }
            if (rv == null)
            {
                myTypes = Assembly.GetCallingAssembly().GetTypes();
                foreach (Type tmpType in myTypes)
                {
                    if (tmpType.FullName == nameSearch)
                    {
                        rv = tmpType.GetConstructor(new Type[] { }).Invoke(new object[] { });
                        break;
                    }
                }
            }
            return rv;
        }
        static public void mergeData(object main, object secondary)
        {
            if (main != null && secondary != null)
            {
                PropertyInfo[] mainObjectProp = main.GetType().GetProperties();
                foreach (PropertyInfo info in mainObjectProp)
                {
                    PropertyInfo secondaryInfo = secondary.GetType().GetProperty(info.Name);
                    ConstructorInfo tmpCon = info.PropertyType.GetConstructor(new Type[] { });
                    if (tmpCon != null)
                    {
                        if (isDefaultValue(main, main.GetType().Name + "_" + info.Name) == 1)
                        {
                            info.SetValue(main, secondaryInfo.GetValue(secondary, null), null);
                        }
                        else
                        {
                            object mainSubClass = info.GetValue(main, null);
                            object secSubClass = secondaryInfo.GetValue(secondary, null);
                            mergeData(mainSubClass, secSubClass);
                        }
                    }
                    else if (isDefaultValue(main, main.GetType().Name + "_" + info.Name) == 1)
                    {
                        info.SetValue(main, secondaryInfo.GetValue(secondary, null), null);
                    }
                }
            }
        }
        static public int isDefaultValue(object obj, string objectName)
        {
            int rv = -1;
            if (obj != null && objectName.Contains("_"))
            {
                string baseObject = objectName.Split('_')[0];
                string varName = objectName.Split('_')[1];
                if (baseObject == obj.GetType().Name)
                {
                    PropertyInfo pInfo = obj.GetType().GetProperty(varName);
                    if (pInfo != null)
                    {
                        object val = pInfo.GetValue(obj, null);
                        if (val is Enum)
                        {
                            if (val.ToString() == "NA")
                                rv = 1;
                            else rv = 0;
                        }
                        else if (val == null || val.ToString() == "")
                        {
                            rv = 1;
                        }
                        else rv = 0;
                    }
                    else
                    {
                        MessageBox.Show("There was an issue here.");
                    }
                }
                else
                {
                    foreach (PropertyInfo info in obj.GetType().GetProperties())
                    {
                        ConstructorInfo tmpCon = info.PropertyType.GetConstructor(new Type[] { });
                        if (tmpCon != null)
                        {
                            int tmpRv = isDefaultValue(info.GetValue(obj, null), objectName);
                            if (tmpRv != -1)
                            {
                                rv = tmpRv;
                                break;
                            }
                        }
                    }
                }
            }
            else rv = 1;
            return rv;
        }
        static public string StyleToString(object style)
        {
            DescriptionAttribute[] attribute =
                    (DescriptionAttribute[])style.GetType().GetField(style.ToString()).GetCustomAttributes(typeof(DescriptionAttribute), false);
            return (attribute.Length > 0) ? attribute[0].Description : style.ToString();
        }
        static public string StyleToString(object style, Type type)
        {
            string rv = "";
            foreach (FieldInfo f1 in type.GetFields())
            {
                if (!f1.IsSpecialName)
                {
                    string basicName = f1.Name;
                    DescriptionAttribute[] attr = (DescriptionAttribute[])f1.GetCustomAttributes(typeof(DescriptionAttribute), false);
                    if (style.ToString() == basicName)
                    {
                        rv = (attr.Length > 0) ? attr[0].Description : basicName;
                        break;
                    }
                    else if (style.ToString() == ((attr.Length > 0) ? attr[0].Description : basicName))
                    {
                        rv = (attr.Length > 0) ? attr[0].Description : basicName;
                        break;
                    }
                }
            }
            return rv;
        }
        static public bool setObjectValue(object obj, object value, string objectName)
        {
            PropertyInfo[] fields = obj.GetType().GetProperties();
            if (objectName.Contains("_"))
            {
                string baseObject = objectName.Split('_')[0];
                string varName = objectName.Split('_')[1];
                foreach (PropertyInfo info in fields)
                {
                    ConstructorInfo tmpCon = info.PropertyType.GetConstructor(new Type[] { });
                    if (tmpCon != null)
                    {
                        object tmp = info.GetValue(obj, null);
                        if (tmp == null)
                            tmp = tmpCon.Invoke(null);
                        if (setObjectValue(tmp, value, objectName))
                        {
                            obj.GetType().GetProperty(info.Name).SetValue(obj, tmp, null);
                            return true;
                        }
                    }
                    else
                    {
                        PropertyInfo tmp = obj.GetType().GetProperty(varName);
                        if (tmp != null && obj.GetType().Name == baseObject)
                        {
                            try
                            {
                                tmp.SetValue(obj, Convert.ChangeType(value, tmp.PropertyType), null);
                            }
                            catch
                            {
                                tmp.SetValue(obj, ObjectStringClass.StringToStyle(value.ToString(), tmp.PropertyType, tmp.GetValue(obj, null)), null);
                            }
                            return true;
                        }
                    }
                }
            }
            return false;
        }
        static public string objectMemberNames(object obj)
        {
            string varibles = "";
            int i = 0;
            PropertyInfo[] fields = obj.GetType().GetProperties();
            string objName = obj.GetType().Name;
            foreach (PropertyInfo info in fields)
            {
                if (i > 0)
                    varibles += "|";
                ConstructorInfo tmpCon = info.PropertyType.GetConstructor(new Type[] { });
                if (tmpCon != null)
                {

                    object tmpObj = info.GetValue(obj, null);
                    if (tmpObj == null && tmpCon != null)
                    {
                        tmpObj = tmpCon.Invoke(null);
                        varibles += objectMemberNames(tmpObj);
                    }
                    else if (tmpObj != null && tmpCon != null)
                    {
                        varibles += objectMemberNames(tmpObj);
                    }
                    else
                    {
                        MessageBox.Show("WTF");
                    }
                }
                else varibles += objName + "_" + info.Name;
                i++;
            }
            return varibles;
        }
        static public Hashtable getColumnAttributes(object obj)
        {
            Hashtable rv = new Hashtable();
            PropertyInfo[] fields = obj.GetType().GetProperties();
            string objName = obj.GetType().Name;
            foreach (PropertyInfo info in fields)
            {
                ConstructorInfo tmpCon = info.PropertyType.GetConstructor(new Type[] { });
                if (tmpCon != null)
                {

                    object tmpObj = info.GetValue(obj, null);
                    if (tmpObj == null && tmpCon != null)
                    {
                        tmpObj = tmpCon.Invoke(null);
                    }
                    Hashtable tmpHash = getColumnAttributes(tmpObj);
                    foreach (DictionaryEntry item in tmpHash)
                    {
                        rv.Add(item.Key, item.Value);
                    }
                }
                ColumnAttribute[] colAttr = (ColumnAttribute[])info.GetCustomAttributes(typeof(ColumnAttribute), false);
                if (colAttr != null && colAttr.Length > 0)
                    colAttr[0].SetTypeOfAttr(info.PropertyType);
                rv.Add(objName + "_" + info.Name, (colAttr != null && colAttr.Length > 0) ? colAttr[0] : null);
            }
            return rv;
        }
        static public string objectValues(object obj)
        {
            return objectValues(obj, ",");
        }
        static public string objectValues(object obj, string splitter)
        {
            return objectValues(obj, splitter, false);
        }
        static public string objectValues(object obj, string splitter, bool includeName)
        {
            return objectValues(obj, splitter, includeName, false);
        }
        static public string objectValues(object obj, string splitter, bool includeName, bool search)
        {
            string varibles = "";
            int i = 0;
            PropertyInfo[] fields = obj.GetType().GetProperties();
            string objName = obj.GetType().Name;
            foreach (PropertyInfo info in fields)
            {
                if (i > 0)
                    varibles += splitter;
                object tmpObj = info.GetValue(obj, null);
                string varString = "";
                ConstructorInfo tmpCon = info.PropertyType.GetConstructor(new Type[] { });
                if (tmpCon != null)
                {

                    if (tmpObj == null && tmpCon != null)
                    {
                        tmpObj = tmpCon.Invoke(null);
                        varibles += objectValues(tmpObj, splitter, includeName);
                    }
                    else if (tmpObj != null && tmpCon != null)
                    {
                        varibles += objectValues(tmpObj, splitter, includeName);
                    }
                    else
                    {
                        if (search)
                            varString = tmpObj == null || tmpObj.ToString() == "" ? "ISNULL" : "'" + tmpObj.ToString().Replace("'", "''") + "'";
                        else
                            varString = tmpObj == null || tmpObj.ToString() == "" ? "NULL" : "'" + tmpObj.ToString().Replace("'", "''") + "'";
                        if (includeName)
                        {
                            string tmp = objName + "_" + info.Name;
                            if (search)
                                tmp += " " + varString;
                            else
                                tmp += "=" + varString;
                            varString = tmp;
                        }
                        varibles += varString;
                    }
                }
                else if (info.PropertyType.BaseType == typeof(Enum))
                {
                    string objString = ObjectStringClass.StyleToString(tmpObj);
                    if (search)
                        varString = tmpObj == null || tmpObj.ToString() == "" ? "ISNULL" : "'" + tmpObj.ToString().Replace("'", "''") + "'";
                    else
                        varString = tmpObj == null || tmpObj.ToString() == "" ? "NULL" : "'" + tmpObj.ToString().Replace("'", "''") + "'";
                    if (includeName)
                    {
                        string tmp = objName + "_" + info.Name;
                        if (search)
                            tmp += " " + varString;
                        else
                            tmp += "=" + varString;
                        varString = tmp;
                    }
                    varibles += varString;
                }
                else
                {
                    if (search)
                        varString = tmpObj == null || tmpObj.ToString() == "" ? "ISNULL" : "'" + tmpObj.ToString().Replace("'", "''") + "'";
                    else
                        varString = tmpObj == null || tmpObj.ToString() == "" ? "NULL" : "'" + tmpObj.ToString().Replace("'", "''") + "'";
                    if (includeName)
                    {
                        string tmp = objName + "_" + info.Name;
                        if (search)
                            tmp += " " + varString;
                        else
                            tmp += "=" + varString;
                        varString = tmp;
                    }
                    varibles += varString;
                }
                i++;
            }
            return varibles;
        }
        static public object StringToStyle(string styleName, Type objectType, object obj)
        {
            object returnVal = null;
            FieldInfo[] fieldInfo = objectType.GetFields();
            foreach (FieldInfo item in fieldInfo)
            {
                DescriptionAttribute[] attribute = (DescriptionAttribute[])item.GetCustomAttributes(typeof(DescriptionAttribute), false);
                string testName;
                if (attribute.Length > 0)
                {
                    testName = attribute[0].Description;
                }
                else testName = item.Name.ToString();
                if (testName == styleName)
                {
                    returnVal = item.GetValue(obj);
                    break;
                }
                else if (item.Name.ToString() == styleName)
                {
                    returnVal = item.GetValue(obj);
                    break;
                }
            }
            return returnVal;

        }
        static public object[] getMemberNamesFromEnum(Type type)
        {
            ArrayList enumValueNames = new ArrayList();
            foreach (FieldInfo f1 in type.GetFields())
            {
                if (!f1.IsSpecialName)
                {
                    string basicName = f1.Name;
                    DescriptionAttribute[] attr = (DescriptionAttribute[])f1.GetCustomAttributes(typeof(DescriptionAttribute), false);
                    enumValueNames.Add((attr.Length > 0) ? attr[0].Description : basicName);
                }
            }
            enumValueNames.Sort();
            return enumValueNames.ToArray();
        }
    }

}
